/***********************************************************************************
 * 文件名： mcu_adc.h
 * 作者： 黄均铭
 * 版本： 1
 * 说明：
 * 		ADC驱动。
 * 修改记录：
 * 	2024年1月8日: 初版。 黄均铭。
 ***********************************************************************************/

#ifndef _MCU_ADC_H_
#define _MCU_ADC_H_

#include "mcu.h"

// 类型定义
typedef u16 adc_t;

// 用来通知转换结果的回调函数类型
typedef void (*adc_result_callback_t)(adc_t result);

// 参数计算

// ADC量程定义
#define ADC_FULL_VALUE 4095

// 内部参考电压通道和电压值
#define ADCH_VREF    30
#define ADC_VOL_VREF 1220

// APIs

// ADC初始化，注意没有开启时钟门控，ADC默认是否使能取决于配置文件
// ADC中断入口函数已经被ADC驱动实现，使用者不要再重复定义。
void Adc_Init();

// [同步]立即转换并获取一次转换结果
// 注意：需要先把对应通道的IO口设置为模拟信号模式
// 将会等待ADC不繁忙时（完成了异步转换任务）返回
adc_t Adc_GetOnce(u8 ch);

// 获取12bit的结果
#define Adc_Get12BitOnce(ch) Adc_GetOnce(ch)

// 获取当前采样通道，扫描状态下不能使用
#define Adc_GetCH() (ADCB->CON2 & ADCB_CON2_ADCSWCHS_Msk)

// 获取当前采样通道结果值，
#define Adc_GetData() (ADCB->DATA[0] & 0xFFF)

// [同步]获取一次有效的（中值滤波）AD值
// 注意：需要先把对应通道的IO口设置为模拟信号模式
// 将首先等待异步转换任务执行完毕。
u16 Adc_GetValue(u8 ch);

// [同步]获取VDD电压，单位mV
// 将首先等待异步转换任务执行完毕。
u16 Adc_GetVDDVoltage();

// [异步]开始一次转换，完成后会通过调用 result_callback 通知转换完成和传递结果
// 将会等待ADC不繁忙时（完成了其它异步转换任务）返回
void Adc_StartOnce(u8 ch, adc_result_callback_t result_callback);

// 关闭ADC
// 注意，ADC关闭状态下开始转换可能会把程序锁死
STATIC_FORCE_IN_LINE void Adc_Disable()
{
    ADCB->LOCK = ADCB_LOCK_WRITE_KEY;
    ADCB->CON &= ~ADCB_CON_ADCEN_Msk;
    ADCB->LOCK = 0x00;
}

// 开启ADC
STATIC_FORCE_IN_LINE void Adc_Enable()
{
    ADCB->LOCK = ADCB_LOCK_WRITE_KEY;
    ADCB->CON |= ADCB_CON_ADCEN_Msk;
    ADCB->LOCK = 0x00;
}

#endif
